﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Granite.DataAnnotations;

namespace Rifts.Models.Characters
{
	partial class Character
	{

		public int IQ
		{
			get { return Get<int>("IQ"); }
			set
			{
				if (Set(value, "IQ"))
					PushIQBonus();
			}
		}

		void PushIQBonus()
		{
			foreach (var skill in Skills)
				skill.IQBonus = SkillBonusFromIQ;
		}


		[CalculatedField("IQ")]
		public int SkillBonusFromIQ
		{
			get
			{
				if (IQ > 30)
					return 16 + (int)Math.Floor((IQ - 30) / 5M);
				if (IQ >= 16 && IQ <= 30)
					return IQ - 14;
				return 0;
			}
		}

		[CalculatedField("IQ")]
		public int PerceptionFromIQ
		{
			get
			{
				if (IQ < 40)
					return 0;
				return (int)Math.Floor((IQ - 30) / 10M);
			}
		}

		[CalculatedField("IQ")]
		public int IllusionSaveFromIQ
		{
			get
			{
				if (IQ <= 30)
					return 0;
				if (IQ <= 33)
					return 1;
				if (IQ <= 36)
					return 2;
				if (IQ <= 39)
					return 3;
				if (IQ <= 42)
					return 4;
				if (IQ <= 45)
					return 5;
				if (IQ <= 48)
					return 6;

				//49+
				return 7;
			}
		}

		public int ME
		{
			get { return Get<int>("ME"); }
			set { Set(value, "ME"); }
		}

		[CalculatedField("ME")]
		public int PsionicSaveFromME
		{
			get
			{
				if (ME <= 15)
					return 0;
				if (ME <= 30)
					return (int)Math.Ceiling((ME - 15) / 2M);
				// ME > 30
				return 8;
			}
		}

		[CalculatedField("ME")]
		public int InsainitySaveFromIQ
		{
			get
			{
				if (ME <= 15)
					return 0;
				if (ME == 16 || ME == 17)
					return 1;
				if (ME == 18)
					return 2;
				if (ME <= 30)
					return (ME - 17);
				// ME > 30
				return 8;
			}
		}


		public int MA
		{
			get { return Get<int>("MA"); }
			set { Set(value, "MA"); }
		}

		[CalculatedField("MA")]
		public int TrustFromMA
		{
			get
			{
				if (MA < 25)
					return 80 - (5 * (25 - MA));
				switch (MA)
				{
					case 25: return 84;
					case 26: return 88;
					case 27: return 92;
					case 28: return 94;
					case 29: return 96;
					default: return 97;
				}
			}
		}



		[CalculatedField("MA")]
		public int IntimidateFromMA
		{
			get { return TrustFromMA; }
		}

		public int PS
		{
			get { return Get<int>("PS"); }
			set
			{
				if (Set(value, "PS"))
				{
					RecalculateStyles();
				}
			}
		}

		public PSType PSType
		{
			get { return Get<PSType>(PSType.Normal, "PSType"); }
			set
			{
				if (Set(value, "PSType"))
				{
					RecalculateStyles();
				}
			}
		}

		[CalculatedField("PS")]
		public int DamageFromPS
		{
			get
			{
				if (PS <= 15)
					return 0;

				return PS - 15;
			}
		}

		[CalculatedField("PS,PSType")]
		public int CarryPounds
		{
			get
			{
				switch (PSType)
				{
					case PSType.Normal:
					case PSType.Augmented:
						if (PS >= 3 && PS <= 16)
							return PS * 10;
						else
							return PS * 20;

					case PSType.Robot:
						if (PS >= 17)
							return PS * 25;
						else
							return PS * 20;

					case PSType.Supernatural:
						if (PS >= 18)
							return PS * 50;
						else
							return PS * 20;
					default:
						return 0;
				}
			}
		}

		[CalculatedField("PS,PSType")]
		public string Carry
		{
			get { return FormatWeight(CarryPounds); }
		}

		[CalculatedField("PS,PSType")]
		public int LiftPounds
		{
			get { return CarryPounds * 2; }
		}

		private static string FormatWeight(decimal pounds)
		{
			if (pounds < 1000)
				return pounds + " lbs";
			else
				return Math.Round((Decimal)pounds / 2000, 1) + " tons";
		}

		[CalculatedField("PS,PSType")]
		public string Lift
		{
			get { return FormatWeight(LiftPounds); }
		}

		public int PP
		{
			get { return Get<int>("PP"); }
			set
			{
				Set(value, "PP");
				RecalculateStyles();
			}
		}

		[CalculatedField("PP")]
		public int ParryDodgeFromPP
		{
			get
			{
				if (PP <= 15)
					return 0;
				if (PP <= 30)
					return (int)Math.Ceiling((PP - 15) / 2M);
				// ME > 30
				return 8;
			}
		}

		[CalculatedField("PP")]
		public int StrikeFromPP
		{
			get
			{
				if (PP <= 15)
					return 0;
				if (PP <= 30)
					return (int)Math.Ceiling((PP - 15) / 2M);
				// ME > 30
				return 8;
			}
		}

		[CalculatedField("PP")]
		public int InitiativeFromPP
		{
			get
			{
				if (PP <= 30)
					return 0;

				if (PP <= 33)
					return 1;
				if (PP <= 36)
					return 2;
				if (PP <= 39)
					return 3;
				if (PP <= 42)
					return 4;
				if (PP <= 45)
					return 5;
				//PP >=46
				return 6;
			}
		}

		public int PE
		{
			get { return Get<int>("PE"); }
			set { Set(value, "PE"); }
		}


		[CalculatedField("PE")]
		public int SaveFromPE
		{
			get
			{
				if (PE <= 15)
					return 0;
				if (PE <= 30)
					return (int)Math.Ceiling((PE - 15) / 2M);
				// PE > 30
				return 8;
			}
		}

		[CalculatedField("PE")]
		public int SaveFromPE2
		{
			get
			{
				if (PE <= 15)
					return 0;
				if (PE <= 18)
					return PE - 12;
				if (PE < 30)
					return 30 - (2 * (30 - PE));

				return PE;
			}
		}

		public int PB
		{
			get { return Get<int>("PB"); }
			set { Set(value, "PB"); }
		}


		[CalculatedField("PB")]
		public int CharmFromPB
		{
			get
			{
				if (PB < 16)
					return 30 - (2 * (16 - PB));

				if (PB < 27)
					return 80 - (5 * (27 - PB));

				switch (PB)
				{
					case 27: return 83;
					case 28: return 86;
					case 29: return 90;
					default: return 92;
				}
			}
		}

		[CalculatedField("PB")]
		public int ImpressFromPB
		{
			get
			{
				return CharmFromPB;
			}
		}
		public int Spd
		{
			get { return Get<int>("Spd"); }
			set { Set(value, "Spd"); }
		}

		[CalculatedField("Spd")]
		public decimal MilesPerHour
		{
			get { return Math.Round((60 * 4 * FeetPerTurn) / 5280M, 1); }
		}

		[CalculatedField("Spd")]
		public int FeetPerTurn
		{
			get { return Spd * 5 * 3; }
		}


		//decimal ActionsForSpd
		//{
		//	get { return Math.Max(1, Actions + Attacks); }
		//}

		//[CalculatedField("Actions,Attacks,Spd")]
		//public decimal FeetPerAction
		//{
		//	get { return Math.Round((decimal)FeetPerTurn / ActionsForSpd, 1); }
		//}

		public int? FlyingSpd
		{
			get { return Get<int?>("FlyingSpd"); }
			set { Set(value, "FlyingSpd"); }
		}

		[CalculatedField("FlyingSpd")]
		public decimal? FlyingMilesPerHour
		{
			get
			{
				if (!FlyingFeetPerTurn.HasValue)
					return null;
				return Math.Round((60 * 4 * FlyingFeetPerTurn.Value) / 5280M, 1);
			}
		}

		[CalculatedField("FlyingSpd")]
		public int? FlyingFeetPerTurn
		{
			get { return FlyingSpd * 5 * 3; }
		}

		//[CalculatedField("Actions,Attacks,Spd")]
		//public decimal? FlyingFeetPerAction
		//{
		//	get
		//	{
		//		if (!FlyingFeetPerTurn.HasValue)
		//			return null;
		//		return Math.Round((decimal)FlyingFeetPerTurn / ActionsForSpd, 1);
		//	}
		//}


	}
}
